/*
 * Copyright (C) 2011, EADS France
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 */
package xowl.gmi.controller;

import java.util.Collection;

/**
 *
 * @author Laurent WOUTERS
 */
public abstract class ASTElement extends Element implements xowl.gmi.view.diagram.SelectableWidget.Actions {
    protected xowl.gmi.model.ast.ASTNode astNode;
    
    public xowl.gmi.model.ast.ASTNode getASTNode() { return astNode; }
    public xowl.gmi.model.ast.Decorator getDecorator() {
        ASTElement astParent = getASTParent();
        if (astParent == null)
            return null;
        xowl.gmi.model.ast.ASTNode parentNode = astParent.getASTNode();
        for (xowl.gmi.model.ast.Decorator decorator : astNode.getAllDecorators()) {
            if (decorator.getParent() == parentNode)
                return decorator;
        }
        return null;
    }
    
    @Override protected ASTElement getNearestAST() { return this; }
    
    public ASTElement(Controller controller, Element parent, xowl.gmi.model.ast.ASTNode ast) {
        super(controller, parent);
        this.astNode = ast;
        setupListener();
    }
    
    @Override protected int getContainedASTCount() { return 1; }
    @Override protected int getLeftSiblingsASTCount(Element divider) { return 0; }
    @Override protected boolean insertAST(xowl.gmi.model.ast.ASTNode node) { return false; }
    @Override protected ASTRemovalStatus removeAST(xowl.gmi.model.ast.ASTNode node) {
        if (node == astNode)
            return ASTRemovalStatus.NodeFound;
        return ASTRemovalStatus.NodeNotFound;
    }
    
    protected abstract void onChildAdd(xowl.gmi.model.ast.ASTNode node);
    protected abstract void onChildRemove(xowl.gmi.model.ast.ASTNode node);
    
    private void setupListener() {
        this.astNode.addPropertyObserver("children", new xowl.interpreter.adapter.ObjectPropertyObserver() {
            @Override public void onAdd(xowl.interpreter.adapter.ProxyObject elem) {
                xowl.gmi.model.ast.ASTNode node = (xowl.gmi.model.ast.ASTNode)elem;
                onChildAdd(node);
            }
            @Override public void onRemove(xowl.interpreter.adapter.ProxyObject elem) {
                xowl.gmi.model.ast.ASTNode node = (xowl.gmi.model.ast.ASTNode)elem;
                onChildRemove(node);
            }
        });
    }
    protected void decommissionListeners() {
        xowl.gmi.model.ast.Decorator decorator = getDecorator();
        if (decorator != null)
            decorator.removeAllObservers();
        this.astNode.removeAllObservers();
    }
    
    protected void setupExecution(xowl.gmi.view.diagram.SelectableWidget widget) {
        for (xowl.gmi.model.ExecutionEntry entry : controller.getExecEntriesFor(astNode.getSymbol().getIRIString()))
            widget.addMenuExecute(entry.getID(), entry.getName());
    }
    
    public void onSelected() { controller.setSelection(this); }
    public void onUnselected(){ controller.setSelection(null); }
    public void onMenuCut() { controller.onEditCut(); }
    public void onMenuCopy() { controller.onEditCopy(); }
    public void onMenuRemove() { controller.onEditRemove(); }
    public void onMenuDelete() { controller.onEditDelete(); }
    public void onMenuExecute(String id) { controller.execute(getModelIRI(), id); }
    
    protected xowl.lang.owl2.IRI getModelIRI() {
        xowl.lang.actions.QueryVariable var = new xowl.lang.actions.QueryVariable();
        var.setName("o");
        xowl.lang.owl2.ObjectPropertyAssertion axiom = new xowl.lang.owl2.ObjectPropertyAssertion();
        axiom.setObjectProperty(controller.getCommandBuilder().getMetaTrace().getHasIRI());
        axiom.setIndividual(astNode.getEntity().getHasIRI());
        axiom.setValueIndividual(var);
        xowl.lang.actions.ValueOf query = new xowl.lang.actions.ValueOf();
        query.addAxioms(axiom);
        query.setOn(var);
        try {
            Collection<xowl.interpreter.QuerySolution> solutions = controller.getRepository().select(query);
            for (xowl.interpreter.QuerySolution solution : solutions)
                return ((xowl.lang.runtime.Entity)solution.getValue(var)).getHasIRI();
        } catch (xowl.interpreter.XOWLException ex) { }
        return null;
    }
}
